﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using ControleRepresentante.Logic;
using ControleRepresentante.Logic.ImpostoHandlers;
using ControleRepresentante.Logic.Models;
using ControleRepresentante.Logic.Repositories;
using ControleRepresentante.Logic.Statistics;
using WebSite.Controllers.ControllerExtensions;
using WebSite.ViewModels.DetailsViewModels;
using WebSite.ViewModels.EditViewModels;
using WebSite.ViewModels.IndexViewModels;
using Attribute = ControleRepresentante.Logic.Models.Attribute;

namespace WebSite.Controllers
{
    public class VendedorController : UsuariosHolderControllerBase<IVendedorRepository, Vendedor, StatisticsBase>
    {
        private readonly IImpostoProvider m_ImpostoProvider;

        public VendedorController(IRepositoryProvider repositoryProvider, ISessionConfiguration sessionConfiguration, IControllerExtensionProvider controllerExtensionProvider, IImpostoProvider impostoProvider)
            : base(repositoryProvider, sessionConfiguration, controllerExtensionProvider)
        {
            m_ImpostoProvider = impostoProvider;
        }

        protected override IAttributeHolderIndexViewModel GetAttributeHolderIndexViewModel(StatisticsBase statistics)
        {
            return new VendedorIndexViewModel(HasPermission(ControleRepresentante.Logic.Models.Area.Pedidos, Operacao.Create));
        }

        protected override AttributeHolderEditViewModel GetEditViewModel()
        {
            return new VendedorEditViewModel();
        }

        protected override AttributeType AttributeType { get { return AttributeType.Vendedor; } }

        protected override string CreateForActionName
        {
            get { return "CreateForVendedor"; }
        }

        protected override UsuariosHolderDetailsViewModel DoGetUsuariosHolderDetailsViewModel(Vendedor model)
        {
            IPedidoRepository pedidoRepository = RepositoryProvider.GetRepository<IPedidoRepository>(m_ImpostoProvider);
            Dictionary<string, double> vendas = pedidoRepository.GetVendasForVendedor(model.Id);
            return new VendedorDetailsViewModel(vendas);
        }

        protected override bool CanDelete(Vendedor model, out string message)
        {
            if (model.Pedidos.Any())
            {
                message = "Vendedor não pode ser excluido porque possui pedidos associados a ele.";
                return false;
            }

            if (model.Clientes.Any())
            {
                message = "Vendedor não pode ser excluido porque possui clientes. Para removê-lo transfira seus clientes para outros vendedores e tente novamente.";
                return false;
            }

            if (model.Users.Any())
            {
                message = "Vendedor não pode ser excluido porque possui usuários com filtros.";
                return false;
            }

            if (model.RelatorioVisitas.Any())
            {
                message = "Vendedor não pode ser excluido porque possui relatorios de visitas associados a ele.";
                return false;
            }

            return base.CanDelete(model, out message);
        }

        protected override void RegisterIndexColumns(IIndexColumnsProvider indexColumnsProvider)
        {
            base.RegisterIndexColumns(indexColumnsProvider);
            indexColumnsProvider.SetDefaultColumns(
                indexColumnsProvider.RegisterColumn("Nome", VendedorIndexColumns.Nome, true),
                indexColumnsProvider[DetailsHolderIndexColumns.Celular],
                indexColumnsProvider[DetailsHolderIndexColumns.Telefone],
                indexColumnsProvider[DetailsHolderIndexColumns.Email],
                indexColumnsProvider.RegisterColumn("Nº de Clientes", VendedorIndexColumns.NumeroClientes));
            indexColumnsProvider.RegisterColumn("Nascimento", VendedorIndexColumns.Nascimento);
            indexColumnsProvider.RegisterColumn("CPF", VendedorIndexColumns.CPF);
            indexColumnsProvider.RegisterColumn("Identidade", VendedorIndexColumns.Identidade);
        }

        protected override Area? Area { get { return ControleRepresentante.Logic.Models.Area.Vendedores; } }

        public ActionResult Search(string nome, string cidade, string bairro, FormCollection formCollection)
        {
            EnsureHasPermission(Operacao.View);

            formCollection.Add(Request.QueryString);

            IAttributeRepository attributeRepository = RepositoryProvider.GetRepository<IAttributeRepository>();
            Dictionary<Attribute, string> attributeMap = GetAttributeMap(attributeRepository, formCollection);

            StatisticsBase statistics;
            IEnumerable<Vendedor> models = Repository.GetModels(nome, cidade, bairro, attributeMap, out statistics, GetPage());

            return Index(models, statistics, formCollection, x =>
                                                                           {
                                                                               VendedorIndexViewModel vendedorIndexViewModel = (VendedorIndexViewModel) x;
                                                                               SetAttributeSearchValues(vendedorIndexViewModel, attributeMap);
                                                                               SetDetailsSearchValues(vendedorIndexViewModel, cidade, bairro);
                                                                               vendedorIndexViewModel.NomeBuscaValue = nome;
                                                                           });
        }
        
        [HttpPost]
        public ActionResult Create(string nome, DateTime? nascimento, string cpf, string identidade, FormCollection formCollection = null)
        {
            EnsureHasPermission(Operacao.Create);
            if (TryUpdateVendedor(nome, nascimento, cpf, identidade, formCollection))
            {
                try
                {
                    Repository.AddModel(Model);
                    Vendedor vendedor = Model;
                    Model = null;
                    return RedirectToAction("Details", vendedor.Id);
                }
                catch (RepositoryException<VendedorErrors> e)
                {
                    switch (e.Error)
                    {
                        case VendedorErrors.DuplicatedNome:
                            ModelState.AddModelError("Nome", "Nome duplicado");
                            break;
                        default:
                            throw;
                    }
                }
            }
            return Create(false);
        }

        [HttpPost]
        public ActionResult Edit(string nome, DateTime? nascimento, string cpf, string identidade, FormCollection formCollection = null)
        {
            EnsureHasPermission(Operacao.Update);
            if (TryUpdateVendedor(nome, nascimento, cpf, identidade, formCollection))
            {
                try
                {
                    Repository.UpdateModel(Model);
                    Guid vendedorId = Model.Id;
                    Model = null;
                    return RedirectToAction("Details", vendedorId);
                }
                catch (RepositoryException<VendedorErrors> e)
                {
                    switch (e.Error)
                    {
                        case VendedorErrors.DuplicatedNome:
                            ModelState.AddModelError("Nome", "Nome duplicado");
                            break;
                        default:
                            throw;
                    }
                }
            }
            return Edit();
        }

        private bool TryUpdateVendedor(string nome, DateTime? nascimento, string cpf, string identidade, FormCollection formCollection)
        {
            Model.Nome = nome;
            Model.CPF = cpf;
            Model.Identidade = identidade;
            Model.Nascimento = nascimento;

            UpdateAttributesToModel(formCollection);

            ModelState.Clear();
            if (String.IsNullOrEmpty(Model.Nome) ||
                Model.Nome.Trim() == String.Empty)
            {
                ModelState.AddModelError("Nome", "*");
            }
            return ModelState.IsValid;
        }
    }
}
